home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH14 / TRANSCND.ASM < prev    next >
Encoding:
Assembly Source File  |  1996-03-24  |  9.1 KB  |  484 lines

  1. ; Transcnd.asm
  2. ;
  3. ; Some transcendental functions for the 80x87 FPU
  4.  
  5.         .xlist
  6.         include     stdlib.a
  7.         includelib    stdlib.lib
  8.         .list
  9.  
  10.         .386
  11.         .387
  12.         option    segment:use16
  13.  
  14. dseg        segment    para public 'data'
  15.  
  16. result        real8    ?
  17.  
  18. ; Some variables we use to test the routines in this package:
  19.  
  20. cotvar        real8    3.0
  21. cotRes        real8    ?
  22. acotRes        real8    ?
  23.  
  24. cscvar        real8    1.5
  25. cscRes        real8    ?
  26. acscRes        real8    ?
  27.  
  28. secvar        real8    0.5
  29. secRes        real8    ?
  30. asecRes        real8    ?
  31.  
  32. sinvar        real8    0.75
  33. sinRes        real8    ?
  34. asinRes        real8    ?
  35.  
  36. cosvar        real8    0.25
  37. cosRes        real8    ?
  38. acosRes        real8    ?
  39.  
  40. Two2xvar    real8    -2.5
  41. Two2xRes    real8    ?
  42. lgxRes        real8    ?
  43.  
  44. Ten2xVar    real8    3.75
  45. Ten2xRes    real8    ?
  46. logRes        real8    ?
  47.  
  48. expVar        real8    3.25
  49. expRes        real8    ?
  50. lnRes        real8    ?
  51.  
  52. Y2Xx        real8    3.0
  53. Y2Xy        real8    3.0
  54. Y2XRes        real8    ?
  55.  
  56.  
  57. dseg        ends
  58.  
  59.  
  60. cseg        segment    para public 'code'
  61.         assume    cs:cseg, ds:dseg
  62.  
  63.  
  64. ; COT(x) - computes the cotangent of st(0) and leaves result in st(0).
  65. ;       st(0) contains x (in radians) and must be between
  66. ;        -2**63 and +2**63
  67. ;       There must be at least one free register on the stack for this
  68. ;       routine to operate properly.
  69. ;
  70. ;    cot(x) = 1/tan(x)
  71.  
  72. cot        proc    near
  73.         fsincos
  74.         fdivr
  75.         ret
  76. cot        endp
  77.  
  78. ; CSC(x) - computes the cosecant of st(0) and leaves result in st(0).
  79. ;       st(0) contains x (in radians) and must be between
  80. ;        -2**63 and +2**63.
  81. ;       The cosecant of x is undefined for any value of sin(x) that
  82. ;        produces zero (e.g., zero or pi radians).
  83. ;       There must be at least one free register on the stack for this
  84. ;       routine to operate properly.
  85. ;
  86. ;    csc(x) = 1/sin(x)
  87.  
  88. csc        proc    near
  89.         fsin
  90.         fld1
  91.         fdivr
  92.         ret
  93. csc        endp
  94.  
  95.  
  96. ; SEC(x) - computes the secant of st(0) and leaves result in st(0).
  97. ;       st(0) contains x (in radians) and must be between
  98. ;        -2**63 and +2**63.
  99. ;       The secant of x is undefined for any value of cos(x) that
  100. ;        produces zero (e.g., pi/2 radians).
  101. ;       There must be at least one free register on the stack for this
  102. ;       routine to operate properly.
  103. ;
  104. ;    sec(x) = 1/cos(x)
  105.  
  106. sec        proc    near
  107.         fcos
  108.         fld1
  109.         fdivr
  110.         ret
  111. sec        endp
  112.  
  113.  
  114. ; ASIN(x)-    Computes the arcsine of st(0) and leaves the result in st(0).
  115. ;        Allowable range: -1<=x<=+1
  116. ;        There must be at least two free registers for this function
  117. ;        to operate properly.
  118. ;
  119. ;    asin(x) = atan(sqrt(x*x/(1-x*x)))
  120.  
  121. asin        proc    near
  122.         fld    st(0)        ;Duplicate X on tos.
  123.         fmul            ;Compute X**2.
  124.         fld    st(0)        ;Duplicate X**2 on tos.
  125.         fld1            ;Compute 1-X**2.
  126.         fsubr
  127.         fdiv            ;Compute X**2/(1-X**2).
  128.         fsqrt            ;Compute sqrt(x**2/(1-X**2)).
  129.         fld1            ;To compute full arctangent.
  130.         fpatan            ;Compute atan of the above.
  131.         ret
  132. asin        endp
  133.  
  134.  
  135. ; ACOS(x)-    Computes the arccosine of st(0) and leaves the
  136. ;            result in st(0).
  137. ;        Allowable range: -1<=x<=+1
  138. ;        There must be at least two free registers for
  139. ;        this function to operate properly.
  140. ;
  141. ;    acos(x) = atan(sqrt((1-x*x)/(x*x)))
  142.  
  143. acos        proc    near
  144.         fld    st(0)        ;Duplicate X on tos.
  145.         fmul            ;Compute X**2.
  146.         fld    st(0)        ;Duplicate X**2 on tos.
  147.         fld1            ;Compute 1-X**2.
  148.         fsubr
  149.         fdivr            ;Compute (1-x**2)/X**2.
  150.         fsqrt            ;Compute sqrt((1-X**2)/X**2).
  151.         fld1            ;To compute full arctangent.
  152.         fpatan            ;Compute atan of the above.
  153.         ret
  154. acos        endp
  155.  
  156.  
  157. ; ACOT(x)-    Computes the arccotangent of st(0) and leaves the
  158. ;            result in st(0).
  159. ;        X cannot equal zero.
  160. ;        There must be at least one free register for
  161. ;        this function to operate properly.
  162. ;
  163. ;    acot(x) = atan(1/x)
  164.  
  165. acot        proc    near
  166.         fld1            ;fpatan computes
  167.         fxch            ; atan(st(1)/st(0)).
  168.         fpatan            ; we want atan(st(0)/st(1)).
  169.         ret
  170. acot        endp
  171.  
  172.  
  173. ; ACSC(x)-    Computes the arccosecant of st(0) and leaves the
  174. ;            result in st(0).
  175. ;        abs(X) must be greater than one.
  176. ;        There must be at least two free registers for
  177. ;        this function to operate properly.
  178. ;
  179. ;    acsc(x) = atan(sqrt(1/(x*x-1)))
  180.  
  181. acsc        proc    near
  182.         fld    st(0)        ;Compute x*x
  183.         fmul
  184.         fld1            ;Compute x*x-1
  185.         fsub
  186.         fld1            ;Compute 1/(x*x-1)
  187.         fdivr
  188.         fsqrt            ;Compute sqrt(1/(x*x-1))
  189.         fld1
  190.         fpatan            ;Compute atan of above.
  191.         ret
  192. acsc        endp
  193.  
  194.  
  195. ; ASEC(x)-    Computes the arcsecant of st(0) and leaves the
  196. ;            result in st(0).
  197. ;        abs(X) must be greater than one.
  198. ;        There must be at least two free registers for
  199. ;        this function to operate properly.
  200. ;
  201. ;    asec(x) = atan(sqrt(x*x-1))
  202.  
  203. asec        proc    near
  204.         fld    st(0)        ;Compute x*x
  205.         fmul
  206.         fld1            ;Compute x*x-1
  207.         fsub
  208.         fsqrt            ;Compute sqrt(x*x-1)
  209.         fld1
  210.         fpatan            ;Compute atan of above.
  211.         ret
  212. asec        endp
  213.  
  214.  
  215. ; TwoToX(x)-    Computes 2**x.
  216. ;        It does this by using the algebraic identity:
  217. ;
  218. ;        2**x = 2**int(x) * 2**frac(x).
  219. ;        We can easily compute 2**int(x) with fscale and
  220. ;        2**frac(x) using f2xm1.
  221. ;
  222. ;        This routine requires three free registers.
  223.  
  224. SaveCW        word    ?
  225. MaskedCW    word    ?
  226.  
  227. TwoToX        proc    near
  228.         fstcw    cseg:SaveCW
  229.  
  230. ; Modify the control word to truncate when rounding.
  231.  
  232.         fstcw    cseg:MaskedCW
  233.         or    byte ptr cseg:MaskedCW+1, 1100b
  234.         fldcw    cseg:MaskedCW
  235.  
  236.         fld    st(0)        ;Duplicate tos.
  237.         fld    st(0)
  238.         frndint            ;Compute integer portion.
  239.  
  240.         fxch            ;Swap whole and int values.
  241.         fsub    st(0), st(1)    ;Compute fractional part.
  242.  
  243.         f2xm1            ;Compute 2**frac(x)-1.
  244.         fld1
  245.         fadd            ;Compute 2**frac(x).
  246.  
  247.         fxch            ;Get integer portion.
  248.         fld1            ;Compute 1*2**int(x).
  249.         fscale
  250.         fstp    st(1)        ;Remove st(1) (which is 1).
  251.  
  252.         fmul            ;Compute 2**int(x) * 2**frac(x).
  253.  
  254.         fldcw    cseg:SaveCW    ;Restore rounding mode.
  255.         ret
  256. TwoToX        endp
  257.  
  258.  
  259.  
  260.  
  261. ; TenToX(x)-    Computes 10**x.
  262. ;
  263. ;        This routine requires three free registers.
  264. ;
  265. ;     TenToX(x) = 2**(x * lg(10))
  266.  
  267.  
  268. TenToX        proc    near
  269.         fldl2t        ;Put lg(10) onto the stack
  270.         fmul        ;Compute x*lg(10)
  271.         call    TwoToX    ;Compute 2**(x * lg(10)).
  272.         ret
  273. TenToX        endp
  274.  
  275.  
  276.  
  277. ; exp(x)-    Computes e**x.
  278. ;        This routine requires three free registers.
  279. ;
  280. ;    exp(x) = 2**(x * lg(e))
  281.  
  282. exp        proc    near
  283.         fldl2e        ;Put lg(e) onto the stack.
  284.         fmul        ;Compute x*lg(e).
  285.         call    TwoToX    ;Compute 2**(x * lg(e))
  286.         ret
  287. exp        endp
  288.  
  289.  
  290.  
  291. ; YtoX(y,x)-    Computes y**x (y=st(1), x=st(0)).
  292. ;        This routine requires three free registers.
  293. ;
  294. ;        Y must be greater than zero.
  295. ;
  296. ;    YtoX(y,x) = 2 ** (x * lg(y))
  297.  
  298. YtoX        proc    near
  299.         fxch         ;Compute lg(y).
  300.         fld1
  301.         fxch
  302.         fyl2x
  303.  
  304.         fmul        ;Compute x*lg(y).
  305.         call    TwoToX    ;Compute 2**(x*lg(y)).
  306.         ret
  307. YtoX        endp
  308.  
  309.  
  310.  
  311.  
  312. ; LOG(x)-    Computes the base 10 logarithm of x.
  313. ;        Usual range for x (>0).
  314. ;
  315. ;    LOG(x) = lg(x)/lg(10).
  316.  
  317. log        proc    near
  318.         fld1
  319.         fxch
  320.         fyl2x        ;Compute 1*lg(x).
  321.         fldl2t        ;Load lg(10).
  322.         fdiv        ;Compute lg(x)/lg(10).
  323.         ret
  324. log        endp
  325.  
  326.  
  327. ; LN(x)-    Computes the base e logarithm of x.
  328. ;        X must be greater than zero.
  329. ;
  330. ;    ln(x) = lg(x)/lg(e).
  331.  
  332. ln        proc    near
  333.         fld1
  334.         fxch
  335.         fyl2x        ;Compute 1*lg(x).
  336.         fldl2e        ;Load lg(e).
  337.         fdiv        ;Compute lg(x)/lg(10).
  338.         ret
  339. ln        endp
  340.  
  341.  
  342.  
  343.  
  344. ; This main program tests the various functions in this package.
  345.  
  346. Main        proc
  347.         mov    ax, dseg
  348.         mov    ds, ax
  349.         mov    es, ax
  350.         meminit
  351.  
  352.         finit
  353.  
  354.  
  355. ; Check to see if cot and acot are working properly.
  356.  
  357.         fld    cotVar
  358.         call    cot
  359.         fst    cotRes
  360.         call    acot
  361.         fstp    acotRes
  362.  
  363.         printff
  364.         byte    "x=%8.5gf, cot(x)=%8.5gf, acot(cot(x)) = %8.5gf\n",0
  365.         dword    cotVar, cotRes, acotRes
  366.  
  367.  
  368. ; Check to see if csc and acsc are working properly.
  369.  
  370.         fld    cscVar
  371.         call    csc
  372.         fst    cscRes
  373.         call    acsc
  374.         fstp    acscRes
  375.  
  376.         printff
  377.         byte    "x=%8.5gf, csc(x)=%8.5gf, acsc(csc(x)) = %8.5gf\n",0
  378.         dword    cscVar, cscRes, acscRes
  379.  
  380.  
  381. ; Check to see if sec and asec are working properly.
  382.  
  383.         fld    secVar
  384.         call    sec
  385.         fst    secRes
  386.         call    asec
  387.         fstp    asecRes
  388.  
  389.         printff
  390.         byte    "x=%8.5gf, sec(x)=%8.5gf, asec(sec(x)) = %8.5gf\n",0
  391.         dword    secVar, secRes, asecRes
  392.  
  393.  
  394. ; Check to see if sin and asin are working properly.
  395.  
  396.         fld    sinVar
  397.         fsin
  398.         fst    sinRes
  399.         call    asin
  400.         fstp    asinRes
  401.  
  402.         printff
  403.         byte    "x=%8.5gf, sin(x)=%8.5gf, asin(sin(x)) = %8.5gf\n",0
  404.         dword    sinVar, sinRes, asinRes
  405.  
  406.  
  407. ; Check to see if cos and acos are working properly.
  408.  
  409.         fld    cosVar
  410.         fcos
  411.         fst    cosRes
  412.         call    acos
  413.         fstp    acosRes
  414.  
  415.         printff
  416.         byte    "x=%8.5gf, cos(x)=%8.5gf, acos(cos(x)) = %8.5gf\n",0
  417.         dword    cosVar, cosRes, acosRes
  418.  
  419.  
  420. ; Check to see if 2**x and lg(x) are working properly.
  421.  
  422.         fld    Two2xVar
  423.         call    TwoToX
  424.         fst    Two2xRes
  425.         fld1
  426.         fxch
  427.         fyl2x
  428.         fstp    lgxRes
  429.  
  430.         printff
  431.         byte    "x=%8.5gf, 2**x  =%8.5gf, lg(2**x)     = %8.5gf\n",0
  432.         dword    Two2xVar, Two2xRes, lgxRes
  433.  
  434.  
  435. ; Check to see if 10**x and l0g(x) are working properly.
  436.  
  437.         fld    Ten2xVar
  438.         call    TenToX
  439.         fst    Ten2xRes
  440.         call    LOG
  441.         fstp    logRes
  442.  
  443.         printff
  444.         byte    "x=%8.5gf, 10**x =%8.2gf, log(10**x)   = %8.5gf\n",0
  445.         dword    Ten2xVar, Ten2xRes, logRes
  446.  
  447.  
  448. ; Check to see if exp(x) and ln(x) are working properly.
  449.  
  450.         fld    expVar
  451.         call    exp
  452.         fst    expRes
  453.         call    ln
  454.         fstp    lnRes
  455.  
  456.         printff
  457.         byte    "x=%8.5gf, e**x  =%8.2gf, ln(e**x)     = %8.5gf\n",0
  458.         dword    expVar, expRes, lnRes
  459.  
  460. ; Check to see if y**x is working properly.
  461.  
  462.         fld    Y2Xy
  463.         fld    Y2Xx
  464.         call    YtoX
  465.         fstp    Y2XRes
  466.  
  467.         printff
  468.         byte    "x=%8.5gf, y     =%8.5gf, y**x         = %8.4gf\n",0
  469.         dword    Y2Xx, Y2Xy, Y2XRes
  470.  
  471.  
  472. Quit:        ExitPgm
  473. Main        endp
  474.  
  475. cseg            ends
  476.  
  477. sseg        segment    para stack 'stack'
  478. stk        byte    1024 dup ("stack   ")
  479. sseg        ends
  480. zzzzzzseg    segment    para public 'zzzzzz'
  481. LastBytes    byte    16 dup (?)
  482. zzzzzzseg    ends
  483.         end    Main
  484.